﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Validation;

namespace Reconciliation.Services
{
    public class Services
    {
        #region -------------------------------------------- Invoice -------------------------------------------------------------

        public static List<Domain.Invoice> GetInvoiceListMonthWise(DateTime startDate, DateTime endDate, int bankID, string invoiceType)
        {
            return Business.Invoice.GetInvoiceListMonthWise(startDate, endDate, bankID, invoiceType);
        }

        public static List<InvoiceComment> GetInvoiceCommentList(int invoiceID)
        {
            InvoiceComment invoiceComment = null;
            List<InvoiceComment> invoiceCommentList = new List<InvoiceComment>();
            List<Domain.InvoiceAuditorComment> domainInvoiceAuditorComment = Business.Invoice.GetListOfInvoiceAuditorComment(invoiceID);
            foreach (Domain.InvoiceAuditorComment iac in domainInvoiceAuditorComment)
            {
                invoiceComment = new InvoiceComment();
                invoiceComment.Comment = iac.Comment;
                invoiceComment.FirstName = iac.User.GivenName;
                invoiceComment.InvoiceID = iac.Invoice.InvoiceID;
                invoiceComment.LastName = iac.User.FamilyName;
                invoiceComment.UserID = iac.User.UserID;
                invoiceCommentList.Add(invoiceComment);
            }
            return invoiceCommentList;
        }


        #endregion

        #region ---------------------------------------------- Order ------------------------------------------------------------

        public static List<Order> GetOrderList(int invoiceID)
        {
            Order order = null;
            List<Order> orderList = new List<Order>();
            List<Domain.Order> domainOrderList = Business.Order.GetOrderList(invoiceID);
            foreach (Domain.Order o in domainOrderList)
            {
                order = new Order();
                order.CaseStatus = o.Case.Status;                
                order.CitDifference = o.CitDifference;
                order.ClientDifference = o.ClientDifference;

                var citPersonnel = (from d in o.Case.CaseAuditorCommentList      
                                     group d by d.DateTime into grp
                                     from g in grp 
                                     where g.DateTime >= grp.Max(m =>m.DateTime)
                                     select new {CitPersonnel = g.User.FamilyName +", " + g.User.GivenName})
                                     .FirstOrDefault();
                order.CitPersonnel = citPersonnel ==null ? "Not Avaiable" : citPersonnel.CitPersonnel;
                order.isAuditorCommented = citPersonnel == null ? false : true;
                var clientPersonnel = (from d in o.Case.CaseClientCommentList      
                                     group d by d.DateTime into grp
                                     from g in grp 
                                     where g.DateTime >= grp.Max(m =>m.DateTime)
                                     select new {ClientPersonnel = g.ClientName}).FirstOrDefault();
                order.CitPersonnel = clientPersonnel ==null ? "Not Avaiable" : clientPersonnel.ClientPersonnel;
                order.isClientCommented = clientPersonnel == null ? false : true;
                order.OrderID = o.OrderID;
                order.StatusDate= o.Case.StatusDate.Value;
                order.CaseID = o.Case.CaseID;
                orderList.Add(order);
            }
            return orderList;
        }

        public static List<StatusOrder> GetOrderList(DateTime startDate, DateTime endDate)
        {
            StatusOrder statusOrder = null;
            List<StatusOrder> statusOrderList = new List<StatusOrder>();
            List<Domain.Order> domainOrderList = Business.Order.GetOrderList(startDate, endDate);
            foreach (Domain.Order o in domainOrderList)
            {
                statusOrder = new StatusOrder();
                statusOrder.CaseStatus = o.Case.Status;
                statusOrder.CitDifference = o.CitDifference;
                statusOrder.OrderID = o.OrderID;
                statusOrder.StatusDate = o.Case.StatusDate.Value;
                statusOrder.InvoiceDate = o.Invoice.InvoiceDate;
                statusOrder.InvoiceStatus = o.Invoice.InvoiceStatus;
                statusOrder.BankCode = o.Bank.BankCode;
                statusOrder.BankID = o.Bank.BankID;
                statusOrder.CaseID = o.Case.CaseID;
                statusOrder.CitExpected = o.CitExpectedReturn;
                statusOrder.CitPhysical = o.CitPhysicalReturn;
                statusOrder.CpcCode = o.Cpc.CpcCode;
                statusOrder.CpcID = o.Cpc.CpcID;
                statusOrder.OrderDate = o.OrderDate;
                statusOrder.isClientCommented = o.Case.CaseClientCommentList.Count == 0 ? false : true;
                statusOrder.isAuditorCommented = o.Case.CaseAuditorCommentList.Count == 0 ? false : true;
                statusOrderList.Add(statusOrder);
            }
            return statusOrderList;
        }

        public static List<OrderDetail> GetPackagingOrderDetail(int orderID)
        {
            OrderDetail orderDetail = null;
            List<OrderDetail> orderDetailList = new List<OrderDetail>();
            List<Domain.OrderDetail> domainOrderDetailList = Business.Order.GetGeneratedOrderDetail(orderID);
            
            foreach(Domain.OrderDetail od in domainOrderDetailList)
            {
                orderDetail = new OrderDetail();
                orderDetail.DenomCode = od.Denomination.DenominationCode;
                orderDetail.DenomID = od.Denomination.DenominationID;
                orderDetail.OrderValue = od.OrderValue;
                orderDetail.OrderID = orderID;
                orderDetail.OrderDetailID = od.OrderDetailID;
                orderDetailList.Add(orderDetail);
            }
            return orderDetailList;
        }

        public static void SetPackagingOrderDetail(List<OrderDetail> orderDetailList)
        {
            try
            {
                if (orderDetailList.Count != 0)
                {
                    Domain.Order domainOrder = new Reconciliation.Domain.Order();
                    domainOrder.OrderID = orderDetailList[0].OrderID;
                    Domain.OrderDetail domainOrderDetail = null;
                    foreach (OrderDetail od in orderDetailList)
                    {
                        domainOrderDetail = new Reconciliation.Domain.OrderDetail();
                        domainOrderDetail.Denomination.DenominationID = od.DenomID;
                        domainOrderDetail.Denomination.DenominationCode = od.DenomCode;
                        domainOrderDetail.OrderDetailID = od.OrderDetailID;
                        domainOrderDetail.CPC = od.OrderValue;// how much pakced                        
                    }

                    Business.Order.SetPackagingOrder(domainOrder);
                }
                else
                {
                    throw new Domain.ReconciliationException("No order detail selected");
                }
            }
            catch (Domain.ReconciliationException ex)
            {
                throw ex;
            }
        }


        public static void SetUnPackagingOrderDetail(List<OrderDetail> orderDetailList)
        {
            try
            {
                if (orderDetailList.Count != 0)
                {
                    Domain.Order domainOrder = new Reconciliation.Domain.Order();
                    domainOrder.OrderID = orderDetailList[0].OrderID;
                    //Updating Status to "Packed"
                    Domain.OrderDetail domainOrderDetail = null;
                    foreach (OrderDetail od in orderDetailList)
                    {
                        domainOrderDetail = new Reconciliation.Domain.OrderDetail();
                        domainOrderDetail.Denomination.DenominationID = od.DenomID;
                        domainOrderDetail.Denomination.DenominationCode = od.DenomCode;
                        domainOrderDetail.OrderDetailID = od.OrderDetailID;
                        domainOrderDetail.CPC = od.OrderValue;// how much pakced
                    }
                    Business.Order.SetUnPackagingOrder(domainOrder);
                }
                else
                {
                    throw new Domain.ReconciliationException("No order detail selected");
                }
            }
            catch (Domain.ReconciliationException ex)
            {
                throw ex;
            }
        }

        public static List<Domain.OrderCycle>  GetOrderCycle(int orderID)
        {
            try
            {
                return Business.Order.GetOrderCycle(orderID);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }        

        #endregion

        #region ------------------------------------------------- User ----------------------------------------------------------------

        public static Domain.User GetUserByUserNameAndPassword(string userName, string password)
        {
            return Business.User.GetUserByUserNameAndPassword(userName, password);
        }
              
        #endregion

        #region ------------------------------------------------- Case ------------------------------------------------------------------

        public static CaseHeader GetCaseHeader(int orderID)
        {
            Domain.Order domainOrder = Business.Order.GetOrder(orderID);
            CaseHeader caseHeader = new CaseHeader();
            caseHeader.CaseStatus = domainOrder.Case.Status;
            caseHeader.CollectionDate = domainOrder.CollectionDate;
            caseHeader.DeliveryDate = domainOrder.DeliveryDate;
            caseHeader.CaseID = domainOrder.Case.CaseID;
            caseHeader.Location = domainOrder.Location;
            return caseHeader;
        }


        public static List<CaseDetail> GetCaseDetail(int orderID)
        {
            List<Domain.OrderDetail> domainOrderDetailList = Business.Order.GetOrderDetail(orderID);
            CaseDetail caseDetail = null;
            List<CaseDetail> caseDetailList = new List<CaseDetail>();
            foreach (Domain.OrderDetail od in domainOrderDetailList)
            {
                caseDetail = new CaseDetail();
                caseDetail.Consensio = od.Consensio;
                caseDetail.CPC = od.CPC;
                caseDetail.Difference = od.ClientDifference;
                caseDetail.ExpectedReturn = od.ExpectedReturn;
                caseDetail.PhysicalReturn = od.PhysicalReturn;
                caseDetail.SST = od.SST;
                caseDetail.StringDenomCode = od.Denomination.DenominationCode;
                caseDetail.OrderDetailID = od.OrderDetailID;
                caseDetailList.Add(caseDetail);
            }
            return caseDetailList;
        }

        public static List<CaseComment> GetCaseAuditorComment(int caseID)
        {
            CaseComment caseComment = null;
            List<CaseComment> caseCommentList = new List<CaseComment>();
            List<Domain.CaseAuditorComment> domainCaseAuditorCommentComment = Business.Case.GetCaseAuditorComment(caseID);
            foreach (Domain.CaseAuditorComment cac in domainCaseAuditorCommentComment)
            {
                caseComment = new CaseComment();
                caseComment.Comment = cac.Comment;
                caseComment.ClientName = cac.User.FamilyName + ", " + cac.User.GivenName;
                caseComment.UserID = cac.User.UserID;
                caseComment.CaseID = caseID;
                caseCommentList.Add(caseComment);
            }
            return caseCommentList;
        }

        public static List<CaseAttachment> GetCaseAttachment(int caseID)
        {
            CaseAttachment caseAttachment = null;
            List<CaseAttachment> casAttachmentList = new List<CaseAttachment>();
            List<Domain.CaseAttachment> domainCaseAttachment = Business.Case.GetCaseAttachment(caseID);
            foreach (Domain.CaseAttachment cac in domainCaseAttachment)
            {
                caseAttachment = new CaseAttachment();
                caseAttachment.Attachment = cac.Attachment;
                caseAttachment.AttachmentFullName = cac.AttachmentName+ "." + cac.AttachmentType;
                caseAttachment.CaseID = caseID;
                casAttachmentList.Add(caseAttachment);
            }
            return casAttachmentList;
        }

        public static List<CaseComment> GetCaseClientComment(int caseID)
        {
            CaseComment caseComment = null;
            List<CaseComment> caseCommentList = new List<CaseComment>();
            List<Domain.CaseClientComment> domainCaseClientCommentComment = Business.Case.GetCaseClientComment(caseID);
            foreach (Domain.CaseClientComment ccc in domainCaseClientCommentComment)
            {
                caseComment = new CaseComment();
                caseComment.Comment = ccc.Comment;
                caseComment.ClientName = ccc.ClientName;
                caseComment.CaseID = caseID;
                caseCommentList.Add(caseComment);
            }
            return caseCommentList;
        }

        public static void SetAttachment(CaseAttachment caseAttachment)
        {
            try
            {
                ValidationResults results = Validation.Validate(caseAttachment);
                if (results.IsValid)
                {
                    Domain.CaseAttachment domainCaseAttachment = new Reconciliation.Domain.CaseAttachment();
                    domainCaseAttachment.Attachment = caseAttachment.Attachment;
                    domainCaseAttachment.AttachmentName = caseAttachment.AttachmentFullName.Substring(0, caseAttachment.AttachmentFullName.LastIndexOf("."));
                    domainCaseAttachment.AttachmentType = caseAttachment.AttachmentFullName.Substring(caseAttachment.AttachmentFullName.LastIndexOf("."));
                    domainCaseAttachment.Case.CaseID = caseAttachment.CaseID;
                    Business.Case.SetAttachment(domainCaseAttachment);
                }
                else
                {
                    StringBuilder builder = new StringBuilder();
                    builder.Append("Validation Errors:<br />");
                    foreach (ValidationResult result in results)
                    {
                        builder.Append(String.Format("- {0}<br />", result.Message));
                        builder.Append(String.Format("Key: {0}, ", result.Key.ToString()));
                        builder.Append(String.Format("Tag: {0}, ", result.Tag));
                        builder.Append(String.Format("Target: {0})<br />", result.Target.ToString()));
                        throw new Domain.ReconciliationException(builder.ToString());
                    }
                }
            }
            catch (Domain.ReconciliationException ex)
            {
                throw ex;
            }
        }

        public static void SetCaseClientComment(CaseComment caseComment)
        {
            try
            {
                ValidationResults results = Validation.Validate(caseComment);
                if (results.IsValid)
                {
                    Domain.CaseClientComment domainCaseClientComment = new Reconciliation.Domain.CaseClientComment();
                    domainCaseClientComment.Case.CaseID = caseComment.CaseID;
                    domainCaseClientComment.ClientName = caseComment.ClientName;
                    domainCaseClientComment.Comment = caseComment.Comment;
                    Business.Case.SetCaseClientComment(domainCaseClientComment);
                }
                else
                {
                    StringBuilder builder = new StringBuilder();
                    builder.Append("Validation Errors:<br />");
                    foreach (ValidationResult result in results)
                    {
                        builder.Append(String.Format("- {0}<br />", result.Message));
                        builder.Append(String.Format("Key: {0}, ", result.Key.ToString()));
                        builder.Append(String.Format("Tag: {0}, ", result.Tag));
                        builder.Append(String.Format("Target: {0})<br />", result.Target.ToString()));
                        throw new Domain.ReconciliationException(builder.ToString());
                    }
                }
            }
            catch (Domain.ReconciliationException ex)
            {
                throw ex;
            }
        }

        public static void SetCaseAuditorComment(CaseComment caseComment)
        {
            try
            {
                ValidationResults results = Validation.Validate(caseComment);
                if (results.IsValid)
                {
                    Domain.CaseAuditorComment domainCaseAuditorComment = new Reconciliation.Domain.CaseAuditorComment();
                    domainCaseAuditorComment.Case.CaseID = caseComment.CaseID;
                    domainCaseAuditorComment.User.UserID = caseComment.UserID;
                    domainCaseAuditorComment.Comment = caseComment.Comment;
                    Business.Case.SetCaseAuditorComment(domainCaseAuditorComment);
                }
                else
                {
                    StringBuilder builder = new StringBuilder();
                    builder.Append("Validation Errors:<br />");
                    foreach (ValidationResult result in results)
                    {
                        builder.Append(String.Format("- {0}<br />", result.Message));
                        builder.Append(String.Format("Key: {0}, ", result.Key.ToString()));
                        builder.Append(String.Format("Tag: {0}, ", result.Tag));
                        builder.Append(String.Format("Target: {0})<br />", result.Target.ToString()));
                        throw new Domain.ReconciliationException(builder.ToString());
                    }
                }
            }
            catch (Domain.ReconciliationException ex)
            {
                throw ex;
            }
        }

        public static void UpdateCase(CaseHeader caseHeader)
        {
            Domain.Case domainCase = new Reconciliation.Domain.Case();
            domainCase.CaseID = caseHeader.CaseID;
            domainCase.Status = caseHeader.CaseStatus;
            Business.Case.UpdateCase(domainCase);
        }

        #endregion      
            
        #region --------------------------------- Expected Return ------------------------------------

        public static List<Domain.Transaction> GetExpectedReturn(int orderID)
        {
            return Business.Transaction.GetExpectedReturn(orderID);
        }

        #endregion
    }
}
